package com.thkj.util;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class OAuthUtil {

    private static Log logger = LogFactory.getLog(OAuthUtil.class);
    public static final String SCOPE_SNSAPI_BASE = "snsapi_base";
    public static final String SCOPE_SNSAPI_USERINFO = "snsapi_userinfo";

    public static final String KEY_GET_USERINFO_STEP2_TOKEN = "access_token";
    public static final String KEY_GET_USERINFO_STEP2_OPENID = "openid";
    
    public static final String GET_CODE_REDIRECT_URI = PropertiesUtils.getProperty("WEBURL") + "/wxOAuthBack";
    public static final String APPID = PropertiesUtils.getProperty("WX_APPID"); 
    public static final String APPSECRET = PropertiesUtils.getProperty("WX_SECRET"); 
    public static final String WX_SESSION_OPENID = "openId"; 
    public static final String SESSION_USER_KEY = "userInfo"; 

    /**
     * 网页授权获取用户基本信息第一步： 用户同意授权，获取code
     * @param appid 公众号的唯一标识
     * @param redirect_uri 授权后重定向的回调链接地址，请使用urlencode对链接进行处理
     * @param scope 应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）
     * @param state 重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节，非必填
     * @return 返回跳转URL
     */
    @SuppressWarnings("deprecation")
	public static String getCode(String appid, String redirect_uri, String scope, String state){
        try{
            redirect_uri = URLEncoder.encode(redirect_uri);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
                "appid="+ appid +
                "&redirect_uri="+ redirect_uri +
                "&response_type=code" +
                "&scope="+ scope +
                "&state=" + state +
                "#wechat_redirect";
        return url;
    }

    /**
     * 第二步：通过code换取网页授权access_token
     * 如果网页授权的作用域为snsapi_base，则本步骤中获取到网页授权access_token的同时，也获取到了openid，snsapi_base式的网页授权流程即到此为止
     * @param appid 公众号的唯一标识
     * @param secret 公众号的appsecret
     * @param code 填写第一步获取的code参数
     * @return 返回保存access_token和openid的map
     */
    public static Map<String, String> getOpenId(String appid, String secret, String code){
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ appid
                +"&secret="+ secret
                +"&code="+ code +"&grant_type=authorization_code";
        Map<String, String> info = null;
        try {
            String data = HttpClient4Util.doGet(url, null);
            if(StringUtils.isBlank(data)){
                logger.error("通过code换取网页授权access_token和openid失败, 没有返回内容");
                return null;
            }
            JSONObject json = JSON.parseObject(data);
            String errcode = json.getString("errcode");
            if(StringUtils.isNotBlank(errcode)){
                logger.error("通过code换取网页授权access_token和openid返回错误信息: " + data);
                return null;
            }

            info = new HashMap<>();
            info.put(KEY_GET_USERINFO_STEP2_TOKEN, json.getString("access_token"));
            info.put(KEY_GET_USERINFO_STEP2_OPENID, json.getString("openid"));
            return info;
        } catch (Exception e) {
            logger.error("通过code换取网页授权access_token和openid失败",e);
        }
        return info;
    }

    /**
     * 第三步：拉取用户信息(需scope为 snsapi_userinfo)
     * @param access_token 第二步获取的token
     * @param openid 第二步获取的openid
     * @return 返回保存用户信息的map
     */
    public static Map<String, String> getUserInfo(String access_token, String openid){
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token="+ access_token +
                "&openid="+ openid +"&lang=zh_CN";
        Map<String, String> info = null;
        try {
            String data = HttpClient4Util.doGet(url, null);
            if(StringUtils.isBlank(data)){
                logger.error("拉取用户信息失败, 没有返回内容");
                return null;
            }
            JSONObject json = JSON.parseObject(data);
            String errcode = json.getString("errcode");
            if(StringUtils.isNotBlank(errcode)){
                logger.error("拉取用户信息返回错误信息: " + data);
                return null;
            }

            info = new HashMap<>();
            Iterator<String> it = json.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                info.put(key, String.valueOf(json.get(key)));
            }
            return info;
        } catch (Exception e) {
            logger.error("拉取用户信息失败",e);
        }
        return null;
    }

}
